package com.itheima.d3_collection_list;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/*
ArrayList：有序，可重复，有索引。
 LinkedList:有序，可重复，有索引。二者的底层实现数据结构不同

 arraylist：
   1.基于数组实现的：
        查询速度快（注意：是根据索引查询数据快）:查询数据通过地址值和索引定位，查询任意数据耗时相同。
        删除效率低：可能需要把后面很多的数据进行前移，来保证数组整个的数据连续性
        添加效率极低：如果是指定数组中间某个位置添加元素，可能需要把后面很多的数据后移，再添加元素；
                   或者添加元素超过数组大小，也可能需要进行数组的扩容，要把原数组内容迁移到扩容的新数组

   2.利用无参构造器创建的集合，会在底层创建一个默认长度为0的数组：elementData数组，用size记录数组大小
    List<String> list1 = new ArrayList<>();
   3.第一次添加元素时，底层会创建一个新的长度为10的数组：也就是把elementData数组扩容为长度为10的新数组
    list1.add("a");
   4.存满时，会扩容1.5倍
   5.如果一次添加多个元素，1.5倍还放不下，则新创建数组的长度以实际为准

ArrayList集合适合什么业务场景？不适合什么业务场景?
    1.适合根据索引查询数据，或者数据量不大的时候
    2.不适合数据量大且需要频繁进行增删操作
 */
/**
 * 目标：掌握LinkedList集合的使用。
 * 链表中的结点是独立的对象，在内存中是不连续的，每个结点包含数据值和下一个结点的地址。
 * 链表的特点1：查询慢，无论查询哪个数据都要从头开始找。
 * 链表的特点2：链表增删相对快
 *
 * LinkedList集合的底层原理
 * 基于双链表实现的。
 * 特点：查询慢，增删相对较快，有头结点和尾节点，但对首尾元素进行增删改查的速度是极快的。
 *
 * public void addFirst(E e)       在该列表开头插入指定的元素
 * public void addLast(E e)        将指定的元素追加到此列表的末尾
 * public E getFirst()             返回此列表中的第一个元素
 * public E getLast()              返回此列表中的最后一个元素
 * public E removeFirst()          从此列表中删除并返回第一个元素
 * public E removeLast()           从此列表中删除并返回最后一个元素
 *
 */

/**
 * LinkedList的应用场景之一：可以用来设计队列
 *  队列特点：先进先出，后进后出
 *
 * LinkedList的应用场景之一：可以用来设计栈
 * 数据进入栈模型的过程称为：压/进栈(push)
 * 数据离开栈模型的过程称为：弹/出栈(pop)
 *  栈特点：先进后出，后进先出
 */
public class ListTest3 {
    public static void main(String[] args) {
        // 1、创建一个队列。
        /*
        注意：不能用Collection创建，多态特点，不能使用子类的特有方法
        这里创建队列需要使用LinkedList的特有方法，所以用LinkedList来接收
         */
        LinkedList<String> queue = new LinkedList<>();
        List<String> s1 = new LinkedList<>();
        ArrayList<String> s2 = new ArrayList<>();
        System.out.println("------------用linkedlist模拟队列---------");
        // 入队
        queue.addLast("第1号人");
        queue.addLast("第2号人");
        queue.addLast("第3号人");
        queue.addLast("第4号人");
        queue.addLast("我是队列");
        System.out.println(queue);
        // 出队
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);

        System.out.println("------------------------用linkedlist模拟栈--------------------------");

        // 2、创建一个栈对象。也是不用多态，因为要用子类的独有功能
        LinkedList<String> stack = new LinkedList<>();
        // 压栈(push)
        // public void push(E e) {   push源码
        //        addFirst(e);
        //    }
        stack.push("第1颗子弹");
        stack.push("第2颗子弹");
        stack.push("第3颗子弹");
        stack.push("第4颗子弹");
        stack.addFirst("我是栈的第五个入栈元素");
        System.out.println(stack);
        // 出栈(pop)
        // public E pop() {     pop源码
        //        return removeFirst();
        //    }
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println("----------我用removeFirst方法----------");
        System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());
        System.out.println(stack);
    }
}
